【AWS Control Tower】監査アカウントからメンバーアカウントへの Lambda アクセスを試す
はじめに
aws-controltower-AuditAdministratorRole という Lambda 実行ロールが AWS Control Towerの 監査(Audit) アカウントには用意されています。 このロールを使って メンバーアカウントへアクセスできます(つまりクロスアカウントアクセス)。 主にセキュリティ周りの対応(修復) を行うためのものです。
- ※1: Assume Role 先のロール名は
aws-controltower-AdministratorExecutionRole
- ※2: 読み取り専用(ReadOnly)用の Lambda 実行ロールも準備されています
(
aws-controltower-AuditReadOnlyRole
)
今回は aws-controltower-AuditAdministratorRole
を使ってみます。
「メンバーアカウントへのアクセス基盤」作成として、最小限の実装を行ってみました。
作ったもの
メンバーアカウント先で sts:GetCallerIdentity を実行するだけ の 「何もしない (接続確認だけする) Lambda関数」 を作ります。
Lambda関数 基本設定
下図のような設定の Lambda関数です。 ランタイムとしては Python 3.8 を使っています。
実行ロールに aws-controltower-AuditAdministratorRole
を指定しています。
Lambda関数 コード
以下のようなコードを作成しています。
import boto3 import logging logger = logging.getLogger() logger.setLevel(logging.INFO) def _sts_client(target_account_id): logger.info('[START] _sts_client') sts_connection = boto3.client('sts') try: # Assume Role role_arn = "arn:aws:iam::%s:role/aws-controltower-AdministratorExecutionRole" % target_account_id role_session_name = "CROSS_ACCOUNT_ACCESS_FROM_CTAUDIT" logger.info("- RoleArn=%s" % role_arn) logger.info("- RoleSessionName=%s" % role_session_name) target = sts_connection.assume_role( RoleArn=role_arn, RoleSessionName=role_session_name, ) except Exception as e: logger.error(e) exit() else: client = boto3.client( 'sts', aws_access_key_id=target['Credentials']['AccessKeyId'], aws_secret_access_key=target['Credentials']['SecretAccessKey'], aws_session_token=target['Credentials']['SessionToken'] ) logger.info('[END] _sts_client') return client def check(sts_client): logger.info('[START] check') try: resp = sts_client.get_caller_identity() logger.info("- Account=%s" % resp['Account']) logger.info("- Arn=%s" % resp['Arn']) except Exception as e: logger.error(e) exit() else: logger.info('[END] check') return {"status": "success"} def lambda_handler(event, context): logger.info('[START] lambda_handler') # Get Client sts_client = _sts_client(event['TargetAccountId']) # Run remediation(check) logger.info('# running check') results = check(sts_client) # End logger.info('[END] lambda_handler') return results
メンバーアカウントのアカウントIDを入力イベントに登録する想定です。
{ "TargetAccountId": "123456789012" }
のような入力イベントです。
(補足) SAMで作成
これらのリソース、設定を AWS SAM(Serverless Application Model) で展開しています。
template.yaml
は以下のとおりです。
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Globals: Function: Runtime: python3.8 Timeout: 600 Handler: app.lambda_handler Architectures: - arm64 Parameters: Project: Type: String Default: "audit-remediation" Resources: CheckFunction: Type: AWS::Serverless::Function Properties: FunctionName: !Sub "${Project}-check-assume-role" Role: !Sub "arn:aws:iam::${AWS::AccountId}:role/aws-controltower-AuditAdministratorRole" CodeUri: src/check_assume_role Outputs: CheckFunction: Description: "Check Function ARN" Value: !GetAtt CheckFunction.Arn
確認
Lambda 関数の実行
以下のようなテストイベント { "TargetAccountId": "123456789012" }
を作成して、実行します。
成功しました。以下のような出力としています。
各種ログの確認
### CloudWatch Logs の確認 at 監査アカウント
/aws/lambda/${関数名}
ロググループに実行ログが保存されます。
### CloudTrail の確認 at 監査アカウント
メンバーアカウントへ Assume Role していることが CloudTrail イベントから確認できました。
### CloudTrail の確認 at メンバーアカウント
メンバーアカウント上で API実行(GetCallerIdentity) できていることを CloudTrail イベントから確認できました。
以下 イベントレコードの userIdentity
抜粋です。
おわりに
AWS Control Tower に用意されている aws-controltower-AuditAdministratorRole
を使ったクロスアカウントアクセスを試してみました。
EventBridge や Step Functions と組み合わせることで、 「セキュリティリスクのあるリソースの自動修復」など 日々のセキュリティ運用に活用できそうです。